/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package DTD;

import DTD.Validador.ValidadorAttList;
import DTD.Validador.ValidadorElement;
import DTD.Validador.ValidadorItem;
import Excepciones.DTDException;
import Utilidades.AtributoEtiqueta;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Stack;

/**
 *
 * @author Administrador
 */
public class DTDValidador {
    private ArrayList<ValidadorItem> reglas; //conjunto de reglas
    private Stack<Box> stk;
    private String error;

    public DTDValidador() {
        reglas = new ArrayList<ValidadorItem>();
        stk = new Stack<Box>();
        error = "";
    }

    public void validarInicioDocumento() throws DTDException {
    }

    
    public void validarFinalDocumento() throws DTDException {
        boolean esValido = stk.empty() && usoCorrectoDeReglas();
        if (!esValido) {
            throw new DTDException("Final inválido de Documento " + error);
        }
    }

    public void validarInicioElemento(String nombreTag, String tagLeido, AtributoEtiqueta[] variables) throws DTDException {
        boolean esValido = false;
        stk.add(new Box());

        if (variables != null && variables.length > 0) {
            String in = getReglas(nombreTag, true, DTDValidadorSintaxis.ATTLIST);
            String ex = getReglas(nombreTag, false, DTDValidadorSintaxis.ATTLIST);

            if (in != null && new ValidadorAttList(in).validar(variables)) {
                esValido = true;
            }
            else if (ex != null && new ValidadorAttList(ex).validar(variables)) {
                esValido = true;
            }
            else if (variables == null && in == null && ex == null) {
                esValido = true;
            }

            if (!esValido) {
                String mje = "Inicio inválido de Elemento: " + nombreTag + " " + tagLeido;
                for (int i = 0; variables != null && i < variables.length; i++) {
                    if (i == 0) {
                        mje = "\nVariables:\n\t";
                    }
                    AtributoEtiqueta variable = variables[i];
                    mje += variable.toString() + "\n\t";
                }
                throw new DTDException(mje);
            }
        }
    }

    public void validarFinalElemento(String nombreTag, String tagLeido) throws DTDException {
        boolean esValido = false;
        Box box = stk.pop();
        String in = getReglas(nombreTag, true, DTDValidadorSintaxis.ELEMENT);
        String ex = getReglas(nombreTag, false, DTDValidadorSintaxis.ELEMENT);

        if (in != null && new ValidadorElement(box, in).validar()) {
            esValido = true;
        }
        else if (ex != null && new ValidadorElement(box, ex).validar()) {
            esValido = true;
        }

        if (stk.isEmpty() == false) {
            stk.peek().addElementoValidado(nombreTag, Box.ELEMENT);
        }

        if (!esValido) {
            throw new DTDException("Final inválido de Elemento: " + nombreTag + " " + tagLeido);
        }
    }

    public void validarContenidoAInsertar(String tagLeido) throws DTDException {
        stk.peek().addElementoValidado(tagLeido, Box.CONTENT);
    }

    /**
     * Agrega una regla al DTDValidador, ya sea que corresponde a la sintaxis de una etiqueta
     * o a un atributo de una etiqueta
     * @param regla String que contiene la regla
     * @param esInterna booleano que indica si la regla es de un DTD interno
     * @param tipoRegla indica si es una regla de una etiqueta o un atributo
     * @throws DTDException
     */
    public void addRegla(String regla, boolean esInterna, int tipoRegla) throws DTDException {
        boolean existe = false; //determina si la regla ya existe
        ValidadorItem vItem = null; //validador del item
        String nombre = regla.split(" ")[1]; //obtengo el nombre de la etiqueta o atributo al que hace referencia la regla

        //verifico si la regla exite
        for (Iterator<ValidadorItem> it = reglas.iterator(); existe == false && it.hasNext();) {
            vItem = it.next();

            if (vItem.getNombre().equals(nombre)) {
                existe = true;
                break;
            }
        }

        if (!existe) {//si no exite, la agrega
            vItem = new ValidadorItem(nombre);
            reglas.add(vItem);
        }
        vItem.addRegla(regla, esInterna, tipoRegla);
    }

    private boolean usoCorrectoDeReglas() {
        boolean resultado = true;

        for (Iterator<ValidadorItem> it = reglas.iterator(); resultado && it.hasNext();) {
            ValidadorItem vItem = it.next();
            resultado = resultado && vItem.usoCorrectoDeReglas();
            if (resultado == false) {
                error = ": " + vItem.getNombre();
            }
        }
        return resultado;
    }

    private String getReglas(String nombreTag, boolean esInterna, int tipoTag) {
        String resultado = null;

        for (Iterator<ValidadorItem> it = reglas.iterator(); resultado == null && it.hasNext();) {
            ValidadorItem vItem = it.next();
            if (vItem.getNombre().equals(nombreTag)) {
                if (tipoTag == DTDValidadorSintaxis.ATTLIST) {
                    resultado = vItem.getReglaAttList(esInterna);
                } else {
                    resultado = vItem.getReglaElement(esInterna);
                }
            }
        }
        return resultado;
    }

}